package edison.jcr.nodetype;

import java.util.ArrayList;
import java.util.List;

import javax.jcr.nodetype.NodeDefinition;
import javax.jcr.nodetype.NodeTypeDefinition;
import javax.jcr.nodetype.PropertyDefinition;

import org.apache.commons.lang.NullArgumentException;

import edison.jcr.SessionContext;
import edison.persistence.NodeDefinitionBean;
import edison.persistence.NodeTypeBean;
import edison.persistence.NodetypeService;
import edison.persistence.PropertyDefinitionBean;
import edison.utils.Converter;

public abstract class NodeTypeDefinitionImpl implements NodeTypeDefinition {
	protected final NodetypeService nodetypeService = null;
	protected String name;

	protected String[] declaredSupertypeNames;
	protected boolean isAbstract;
	protected boolean isMixin;
	protected boolean hasOrderableChildNodes;
	protected String primaryItemName;
	protected boolean isQueryable;
	protected List<PropertyDefinition> declaredPropertyDefinitions;
	protected List<NodeDefinition> declaredChildNodeDefinitions;

	protected final SessionContext context;

	
	NodeTypeDefinitionImpl(SessionContext context){
		if(context==null)
			throw new NullArgumentException("context");
		this.context = context;		
	}
	
	NodeTypeDefinitionImpl(SessionContext context,NodeTypeBean bean) {
		this(context);
		if(bean==null)
			throw new NullArgumentException("bean");
		this.name = bean.getName();
		this.declaredSupertypeNames =Converter.toArray( bean.getDeclaredSupertypeNames());
		this.primaryItemName = bean.getPrimaryItemName();
		this.isAbstract = bean.isAbstract();
		this.isMixin = bean.isMixin();
		this.hasOrderableChildNodes = bean.isHasOrderableChildNodes();
		this.isQueryable = bean.isQueryable();
		this.declaredPropertyDefinitions = toPropertyDefinitions(bean.getDeclaredPropertyDefinitions());
		this.declaredChildNodeDefinitions = toNodeDefinitions(bean.getDeclaredChildNodeDefinitions());
	}
	
	private List<PropertyDefinition> toPropertyDefinitions(List<PropertyDefinitionBean> propertyDefinitionBeans) {
		List<PropertyDefinition> propertyDefinitions = new ArrayList<PropertyDefinition>();
		for (PropertyDefinitionBean propertyDefinitionBean : propertyDefinitionBeans) {
			propertyDefinitions.add(new PropertyDefinitionImpl(context, propertyDefinitionBean));
		}
		
		return propertyDefinitions;
	}
	
	private List<NodeDefinition> toNodeDefinitions(List<NodeDefinitionBean> nodeDefinitionBeans) {
		List<NodeDefinition> nodeDefinitions = new ArrayList<NodeDefinition>();
		for (NodeDefinitionBean nodeDefinitionBean : nodeDefinitionBeans) {
			nodeDefinitions.add(new NodeDefinitionImpl(context, nodeDefinitionBean));
		}
		
		return nodeDefinitions;
	}

	public String getName() {
		return name;
	}

	public String[] getDeclaredSupertypeNames() {
		return declaredSupertypeNames;
	}

	public boolean isAbstract() {
		return isAbstract;
	}

	public boolean isMixin() {
		return isMixin;
	}

	public boolean hasOrderableChildNodes() {
		return hasOrderableChildNodes;
	}

	public boolean isQueryable() {
		return isQueryable;
	}

	public String getPrimaryItemName() {
		return primaryItemName;
	}

	public PropertyDefinition[] getDeclaredPropertyDefinitions() {
		return declaredPropertyDefinitions.toArray(new PropertyDefinition[] {});
	}

	public NodeDefinition[] getDeclaredChildNodeDefinitions() {
		return declaredChildNodeDefinitions.toArray(new NodeDefinition[] {});
	}

}